<?php

namespace magein\think\utils\service;

use magein\think\utils\constants\Code;
use magein\utils\Result;
use think\db\exception\DbException;
use think\Model;
use think\Validate;

class BaseService
{

    /**
     * @var Model
     */
    protected $model = null;

    /**
     * @var array
     */
    protected $fields = [];

    /**
     * 追加字段
     * @return array
     */
    protected function append(): array
    {
        return [];
    }

    /**
     * 关联查询
     * @return array
     */
    protected function with(): array
    {
        return [];
    }

    protected function exportFields()
    {
        return $this->fields;
    }

    /**
     * @param Model $model
     * @return self
     */
    public static function setModel(Model $model)
    {
        $self = new self();
        $self->model = $model;
        if ($self->fields) {
            $self->model->field($self->fields);
        }
        return $self;
    }

    /**
     * @return Model
     */
    protected function getModel()
    {
        $model = $this->model;

        if (is_string($model)) {
            $model = new $model;
        }

        return $model;
    }

    /**
     * @return array|\think\Collection
     */
    public function select()
    {
        try {
            $data = $this->getModel()->select();
        } catch (DbException $exception) {
            $data = [];
        }

        return $data ?: [];
    }

    /**
     * @param int $page_size
     * @return \think\Paginator
     */
    public function paginate(int $page_size = null)
    {

        if (empty($page_size)) {
            $page_size = request()->param('page_size');
        }

        if ($page_size <= 0 || $page_size > 200) {
            $page_size = 20;
        }

        try {
            $data = $this->getModel()->with($this->with())->field($this->exportFields())->paginate(
                [
                    'list_rows' => $page_size,
                    'var_page' => 'page_id',
                ]
            );
        } catch (DbException $exception) {
            $data = null;
        }

        return $data;
    }

    /**
     * @param $id
     * @param $pk
     * @return array|mixed|Model|null
     */
    public function detail($id = null, $pk = 'id')
    {
        if (empty($id)) {
            $id = request()->param('id');
        }

        if (empty($id) || empty($pk)) {
            return null;
        }

        try {
            $data = $this->getModel()->where($pk, $id)->field($this->exportFields())->find();
        } catch (DbException $e) {
            $data = null;
        }


        return $data ?: null;
    }

    /**
     * @return Validate|null
     */
    protected function validate(): ?\think\Validate
    {
        return null;
    }

    /**
     * @param $data
     * @return Result|\think\model\contract\Modelable
     */
    public function create($data = [])
    {
        if (empty($data)) {
            return Result::error('新增字段不能为空', Code::SERVICE_SAVE_EMPTY);
        }

        $validate = $this->validate();
        if ($validate) {
            if ($validate->hasScene('create')) {
                $result = $validate->scene('create')->check($data);
            } else {
                $result = $validate->check($data);
            }
            if (!$result) {
                return Result::error($validate->getError(), Code::VALIDATE_ERROR);
            }
        }


        return $this->getModel()->create($data);
    }

    /**
     * @param $data
     * @return bool|Result
     * @throws DbException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function update($data = [])
    {
        if (empty($data)) {
            return Result::error('更新字段不能为空', Code::SERVICE_SAVE_EMPTY);
        }

        $id = $data['id'] ?? '';
        if (empty($id)) {
            return Result::error('更新参数不能为空', Code::SERVICE_KEY_EMPTY);
        }
        unset($data['id']);

        $record = $this->getModel()->find($id);
        if (empty($record)) {
            return Result::error('数据记录不存在');
        }

        $validate = $this->validate();
        if ($validate) {
            if ($validate->hasScene('update')) {
                $result = $validate->scene('update')->check($data);
            } else {
                $result = $validate->check($data);
            }
            if (!$result) {
                return Result::error($validate->getError(), Code::VALIDATE_ERROR);
            }
        }

        return $record->save($data);
    }

    /**
     * @param $id
     * @return Result|mixed
     */
    public function delete($id = null)
    {
        if (empty($id)) {
            $id = request()->delete('id');
        }

        if (empty($id)) {
            return Result::error('删除参数错误', Code::SERVICE_KEY_EMPTY);
        }

        if (is_string($id)) {
            if (strpos(',', $id)) {
                $id = explode(',', $id);
            }
        }

        if (!is_array($id)) {
            $id = [$id];
        }

        $class = get_class($this->getModel());

        return call_user_func_array([$class, 'destroy'], $id);
    }
}